
/*
    Software License

    Copyright (C) 2021-05-24  Xoronos

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

/*
    Liabilities

    The software is provided "AS IS" without any warranty of any kind, either expressed,
    implied, or statutory, including, but not limited to, any warranty that the software
    will conform to specifications, any implied warranties of merchantability, fitness
    for a particular purpose, and freedom from infringement, and any warranty that the
    documentation will conform to the software, or any warranty that the software will
    be error free.

    In no event shall Xoronos be liable for any damages, including, but not limited to,
    direct, indirect, special or consequential damages, arising out of, resulting from,
    or in any way connected with this software, whether or not based upon warranty,
    contract, tort, or otherwise, whether or not injury was sustained by persons or
    property or otherwise, and whether or not loss was sustained from, or arose out of
    the results of, or use of, the software or services provided hereunder.

    To request the provided software under a different license you can contact us at
    support@xoronos.com
*/

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "examples.h"
#include "xrn_common.h"

    /////////////////////////////////////////////////////
    //                   Introduction                  //
    /////////////////////////////////////////////////////
    // This code example shows how to generate and     //
    // merge blocks of data. Furtermore, the code      //
    // example shows also how to check if a block      //
    // contains the entire file, and how to strip the  //
    // block header.                                   //
    /////////////////////////////////////////////////////

int create_blocks_from_file(
 )
{

    FILE *input_fp;
    FILE *block0_fp;
    FILE *block1_fp;
    FILE *merged_fp;
    FILE *stripped_fp;

    uint32_t tag;
    uint64_t offset;
    uint64_t length;
    uint64_t total_length;

    FILE *files[XRN_MAX_MERGE_PARALLELISM];
    uint8_t num_inputs;

    /////////////
    // Logging //
    /////////////

    // Set the default logging file streams
    // errors -> stderr
    // warnings -> stdout
    // notifications -> stdout
    // debug -> stdout

    xrn_set_default_log(  );

    // To change the default logging you can use the functions below,
    // where fp is the opened file pointer
    // 
    // xrn_change_error_log( fp )
    // xrn_change_warning_log( fp )
    // xrn_change_notification_log( fp )
    // xrn_change_debug_log( fp )

    // get a random tag (like a file name stored in the header)

    tag = ( uint32_t ) rand(  );

    /////////////////////////////////
    // create two continous blocks //
    /////////////////////////////////

    input_fp = fopen( "lorem_ipsum.txt", "rb" );

    // get the total length

    fseek( input_fp, 0L, SEEK_END );
    total_length = ( uint64_t ) ftell( input_fp );
    fseek( input_fp, 0L, SEEK_SET );

    block0_fp = fopen( "block0.txt", "wb" );

    offset = 0;
    length = ( uint64_t ) ( ( ( uint64_t ) rand(  ) ) % total_length );

    printf( "create first block...\n" );
    if ( XSUCCESS != xrn_make_block( input_fp,  // the input file pointer
                                     block0_fp, // the output block file pointer
                                     tag,       // the file tag 
                                     offset,    // the file offset 
                                     length     // the length of the file
          ) ) {
        fclose( input_fp );
        fclose( block0_fp );
        return -1;
    }

    fclose( input_fp );
    fclose( block0_fp );

    input_fp = fopen( "lorem_ipsum.txt", "rb" );
    block1_fp = fopen( "block1.txt", "wb" );

    offset = length;
    length = total_length - offset;

    printf( "create second block...\n" );
    if ( XSUCCESS != xrn_make_block( input_fp,  // the input file pointer 
                                     block1_fp, // the output block file pointer
                                     tag,       // the file tag 
                                     offset,    // the file offset 
                                     length     // the length of the file
          ) ) {
        fclose( input_fp );
        fclose( block1_fp );
        return -1;
    }

    fclose( input_fp );
    fclose( block1_fp );

    ///////////////////////////////////////////////////////
    // merge the two blocks and do not exptect any fault //
    ///////////////////////////////////////////////////////

    block0_fp = fopen( "block0.txt", "rb" );
    block1_fp = fopen( "block1.txt", "rb" );
    merged_fp = fopen( "merged.txt", "wb" );

    files[0] = block0_fp;
    files[1] = block1_fp;
    num_inputs = 2;

    printf( "merge the two blocks...\n" );
    if ( XSUCCESS != xrn_join_blocks( files,    // the file pointers of the input blocks
                                      num_inputs,       // the number of inputs
                                      merged_fp // the output merged block
          ) ) {
        fclose( merged_fp );
        fclose( block0_fp );
        fclose( block1_fp );
        return -1;
    }

    fclose( merged_fp );
    fclose( block0_fp );
    fclose( block1_fp );

    ///////////////////////////////////
    // check if the file is complete //
    ///////////////////////////////////

    printf( "check if the block contains the entire information...\n" );
    merged_fp = fopen( "merged.txt", "rb" );
    if ( XNCOMPLETE == xrn_check_complete_blocks( merged_fp ) ) {
        return -1;
    }

    fclose( merged_fp );

    //////////////////
    // strip header //
    //////////////////

    stripped_fp = fopen( "stripped.txt", "wb" );
    merged_fp = fopen( "merged.txt", "rb" );

    printf( "strip the header from the block file...\n" );
    if ( XSUCCESS != xrn_strip_header_from_block( merged_fp,    // the input block file
                                                  stripped_fp   // the plain text output file
          ) ) {
        fclose( merged_fp );
        fclose( stripped_fp );
        return -1;
    }

    fclose( merged_fp );
    fclose( stripped_fp );

    return 0;

}

